﻿using Sustainalytics.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Sustainalytics.Insights.Service;
using Sustainalytics.Replication.Publisher;
using Newtonsoft.Json;
using Sustainalytics.Utils.Serilog;

namespace Sustainalytics.Insights.BusinessLogic
{

    //todo add server validation
    public class InsightsBussinesLogic : IInsightBussinesLogic
    {
        private readonly IInsightRepository _repository;
        private readonly ServiceBusPublisher _serviceBusPublisher;

        public InsightsBussinesLogic(IInsightRepository repository, ServiceBusPublisher serviceBusParams)
        {
            this._repository = repository;
            this._serviceBusPublisher = serviceBusParams;
        }

        public virtual bool Create(Insight newInsight)
        {
            ValidateInsight(newInsight);
            newInsight.AddedByUserName = ClaimsPrincipal.Current.Claims.Where(s => s.Type == ClaimTypes.GivenName)
                    .Select(s => s.Value)
                    .SingleOrDefault() + " " + ClaimsPrincipal.Current.Claims.Where(s => s.Type == ClaimTypes.Surname)
                        .Select(s => s.Value)
                        .SingleOrDefault();

            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(newInsight), ReplicationUtils.EntityType.Insight, ReplicationUtils.Operation.Create);
            return _repository.Create(newInsight);
        }

        public virtual bool Update(Insight insight)
        {
            ValidateInsight(insight);
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(insight), ReplicationUtils.EntityType.Insight, ReplicationUtils.Operation.Update);
            return _repository.Update(insight);
        }

        public virtual Insight Read(Guid id)
        {
            return _repository.Read(id);
        }

        public virtual bool Update(List<Tuple<Guid, InsightState>> list)
        {
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(list), ReplicationUtils.EntityType.Insight, ReplicationUtils.Operation.UpdateBatch);
            return _repository.Update(list);
        }

        public virtual bool Delete(Guid id)
        {
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(id), ReplicationUtils.EntityType.Insight, ReplicationUtils.Operation.Delete);
            return _repository.Delete(id);
        }

        public virtual List<Insight> Read(DateTime publishedOnDate, string titlePart, InsightState? state, Guid? insightTopicId, Guid? insightSectorId, DateTime noOlderThan,
            int? skip, int? take, string orderby, bool orderAsc)
        {
            return _repository.Read(publishedOnDate, titlePart, state, insightTopicId, insightSectorId, noOlderThan, skip, take, orderby, orderAsc);
        }

        public virtual long ReadCount(DateTime publishedOnDate, string titlePart, InsightState? state, Guid? insightTopicId, Guid? insightSectorId, DateTime noOlderThan)
        {
            return _repository.ReadCount(publishedOnDate, titlePart, state, insightTopicId, insightSectorId, noOlderThan);
        }

        public virtual bool Delete(List<Guid> ids)
        {
            _serviceBusPublisher.SendMessage(JsonConvert.SerializeObject(ids), ReplicationUtils.EntityType.Insight, ReplicationUtils.Operation.DeleteBatch);
            return _repository.Delete(ids);
        }

        private void ValidateInsight(Insight insight)
        {
            if (!(insight.Id != default(Guid)))
                throw new ArgumentOutOfRangeException("Id");

            if (string.IsNullOrEmpty(insight.Title))
                throw new ArgumentOutOfRangeException("Title");

            if (insight.Title.Length > 200)
                throw new ArgumentOutOfRangeException("Title too long, limit is 200 chars");

            if (string.IsNullOrEmpty(insight.Summary))
                throw new ArgumentOutOfRangeException("Summary");

            if (insight.Summary.Length > 5000)
                throw new ArgumentOutOfRangeException("Summary too long, limit is 5000 chars");

            if (!(insight.InsightTopicId != default(Guid)))
                throw new ArgumentOutOfRangeException("InsightTopicId");

            if (!(insight.InsightSectorId != default(Guid)))
                throw new ArgumentOutOfRangeException("InsightSectorId");

            if (!(insight.ImageId != default(Guid)))
                throw new ArgumentOutOfRangeException("ImageId");

            if (!(insight.FileId != default(Guid)))
                throw new ArgumentOutOfRangeException("FileId");

            if (!(insight.DatePublished != default(DateTime)))
                throw new ArgumentOutOfRangeException("DatePublished");

            if (!(insight.DateUnPublished != default(DateTime)))
                throw new ArgumentOutOfRangeException("DateUnPublished");

            if (!(insight.DatePublished < insight.DateUnPublished))
                throw new ArgumentOutOfRangeException("DatePublished should be older then date DateUnPublished");
        }
    }
}

